﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.IO;

namespace TestRunner
{
    class Program
    {
        static void Main(string[] args)
        {
            string path;
            if (args.Contains("-d") || args.Contains("-D"))
            {
                var debugPath = Environment.GetEnvironmentVariable("PDXCXXD");
                if (string.IsNullOrEmpty(debugPath)) debugPath = "../build/Debug/bin/pdxcxx.exe";
                path = debugPath;
            }
            else
            {
                var releasePath = Environment.GetEnvironmentVariable("PDXCXX");
                if (string.IsNullOrEmpty(releasePath)) releasePath = "../build/Release/bin/pdxcxx.exe";
                path = releasePath;
            }
            path = path.Replace('/', '\\');
             
            var processInfo = new ProcessStartInfo(path);
            processInfo.CreateNoWindow = true;
            processInfo.UseShellExecute = false;
            processInfo.RedirectStandardOutput = true;
            processInfo.StandardOutputEncoding = System.Text.Encoding.ASCII;

            bool ok = true;
            foreach (var file in Directory.EnumerateFiles(Directory.GetCurrentDirectory(), "*.cpp"))
            {
                Console.Write(file + "...");
                var baseFilename = file.Substring(0, file.Length - 3);
                var actualResultFile = baseFilename + "txt";
                var expectedResultFile = baseFilename + "test";

                processInfo.Arguments = file;
                var process = Process.Start(processInfo);
                var outputStream = new StreamWriter(actualResultFile);
                StreamForwarding.forwardUntilEOF(process.StandardOutput, outputStream);

                process.WaitForExit();
                outputStream.Close();

                if (process.ExitCode == 0)
                {
                    if (args.Contains("-c") || args.Contains("-C"))
                    {
                        Console.WriteLine("UPDATED");
                        File.Copy(actualResultFile, expectedResultFile, true);
                    }
                    else
                    {
                        if (File.Exists(expectedResultFile))
                        {
                            var expected = File.ReadAllBytes(expectedResultFile);
                            var actual = File.ReadAllBytes(actualResultFile);
                            if (expected.SequenceEqual(actual))
                            {
                                Console.WriteLine("OK");
                            }
                            else
                            {
                                Console.WriteLine("FAILED (different result)");
                                ok = false;
                            }
                        }
                        else
                        {
                            Console.WriteLine("OK");
                        }
                    }
                }
                else
                {
                    //TODO: will need to handle failure exit code as normal case as pdxcxx is eventually supposed to return non-zero when detecting errors
                    Console.WriteLine("FAILED (code " + process.ExitCode + ")");
                    ok = false;
                }
            }

            if (!ok)
            {
                Console.WriteLine("FAILURE: One or more tests failed.");
                Environment.Exit(1);
            }
        }
    }

    class StreamForwarding
    {
        public static async void forwardUntilEOF(StreamReader reader, StreamWriter writer)
        {
            var buffer = new char[8000];
            for (; ; )
            {
                int nRead = await reader.ReadAsync(buffer, 0, buffer.Length);
                if (nRead == 0) break;

                writer.Write(buffer, 0, nRead);
            }
        }
    }
}
